"""主函数"""
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QMessageBox, QWidget
from UI.untitled import Ui_MainWindow
from JsonProtocolParser.Json_Analysis import JsonProtocol
from LogControl.log_init import Log_Config
from ProjectManager._11BS_protocol import Protocol_11BS
from ProjectManager._11B_protocol import Protocol_11B
from ProjectManager._15_protocol import Protocol_15
from ProjectManager._15s_protocol import Protocol_15s
from ThemeControl.theme_control import theme_control
from ProjectManager.public_data_process import PublicDataProcess
from NetWork.Udp import UdpLogic
from TimerOutDetection.timerout import TimeoutHandler
import sys
import os
import platform
import subprocess
from ProgressBar.Progress_Bar import ProgressBarWindow

"""提示框"""
class MessageBox:
    """消息提示"""

    @staticmethod
    def msg_box(notice, msg):
        """消息提示框"""
        msg_box = QMessageBox(QMessageBox.Information, notice, msg)
        msg_box.exec_()


class MainWindow(QMainWindow, Ui_MainWindow):
    project_protocol = pyqtSignal(str)  # 项目类型协议类型信号
    project_recv_data_signal = pyqtSignal(bytes)  # 项目类型协议类型信号:接收到数据
    project_erro_signal = pyqtSignal(dict)  # 项目类型协议类型信号:接收到错误
    project_data_process_signal = pyqtSignal()  # 接收完下位机所有数据之后的处理信号
    project_timerout_signal = pyqtSignal()  # 超时信号

    def __init__(self):
        super(MainWindow, self).__init__()
        # 初始化界面
        self.setupUi(self)

        # 错误数据标志位
        self.erro_flag = False

        # 创建一个UDP对象
        self.udp_logic = UdpLogic()

        # 创建一个协议解析对象
        self.Json_protocol = JsonProtocol()

        # 创建一个日志对象
        self.__log = Log_Config()

        # 11Bs模块的对象
        self.protocol_11bs = Protocol_11BS(self)
        # 11B模块的对象
        self.protocol_11b = Protocol_11B(self)
        # 15模块的对象
        self.protocol_15 = Protocol_15(self)
        # 15s模块的对象
        self.protocol_15s = Protocol_15s(self)
        # 创建一个公共数据处理对象
        self.public_data_process = PublicDataProcess(self.Json_protocol)

        # 创建超时检测机制的实例话对象
        self.time_out = TimeoutHandler(1000, 0.5, self.timeout_callback)

        # 设置主题
        theme_control.theme_set_light(self)

        # 发送、接收、错误的计数器
        self.send_count = 0
        self.rec_count = 0
        self.erro_count = 0

        # 启动测试功能码
        self.start_test = '01'
        # 正在传输功能码
        self.trans_flag = '02'
        # 传输完成功能码
        self.trans_over = '03'
        # 传输错误功能码
        self.trans_erro = 'ff'
        # 接收消息体的次数
        self.rec_count = 0

        # 创建进度条
        self.process_bar = ProgressBarWindow()

        # 复位按钮初始化
        self.__ResetLable_Init()

        # 设置UDP状态信息的信号和槽函数
        self.udp_logic.udp_signal_write_msg.connect(self.__on_udp_signal_write_msg)
        # 设置UDP接收数据的信号和槽函数
        self.udp_logic.udp_signal_write_info.connect(self.__on_udp_signal_write_info)
        # 项目类型的信号和槽函数
        self.project_protocol.connect(self.__on_project_protocol)
        # 项目类型
        self.project_recv_data_signal.connect(self.__on_project_recv_data_signal)
        # 错误数据的表格处理
        self.project_erro_signal.connect(self.__on_project_erro_signal)
        # 设置解析数据的槽函数
        self.project_data_process_signal.connect(self.__on_project_data_process_signal)
        # 设置接收数据的超时信号
        self.project_timerout_signal.connect(self.__on_project_timerout_dispaly)

        # 保存数据长度
        self.lengh = 0
        # 记录上一次的通道编号值
        self.channel_index = 0
        # 保存处理后的错误通道号的数据
        self.recv_erro_info_dict = {}
        # 创建接收消息的容器
        self.recv_list = []
        # 创建一个列表来存储异常的值
        self.abnormal_signals = []
        # 定义每个项目的通道数量
        self.channel_length = [219, 373, 99, 123]  # 通道长度:每个项目的通道长度不相同

        # 隐藏停止按钮
        self.Stop.hide()
        # 隐藏标签按钮
        self.label_125.hide()

    """*************************** 对接收到的列表数据进行解析的槽函数 ***********************************"""

    def __on_project_data_process_signal(self):
        """
        解析数据的槽函数
        :return:
        """
        # 获取列表容器的长度
        length = len(self.recv_list)

        # 数据分组:将对应通道为1的错误下标收集到相同的一个字典里面
        for item in self.recv_list:
            board_high_idx = item[3]
            board_high_signal = item[4]

            # 越界判断
            if int(board_high_idx) > self.channel_length[int(self.Json_protocol.dataprotocol) - 1] or \
                    int(board_high_signal) > self.channel_length[int(self.Json_protocol.dataprotocol) - 1]:
                self.__log.logger.error("接受数据的通道编号错误")
                # self.process_bar.close_progress_bar()
                MessageBox.msg_box("错误", "通道编号错误")
                return None

            # 添加错误通道号到字典内
            if board_high_idx != board_high_signal:
                # 添加到字典的键
                if board_high_idx not in self.recv_erro_info_dict:
                    self.recv_erro_info_dict[board_high_idx] = []
                self.recv_erro_info_dict[board_high_idx].append(board_high_signal)

        if len(self.recv_erro_info_dict):
            # 从错误的字典信息中提取为列表类型
            for index in self.recv_erro_info_dict.keys():
                self.abnormal_signals.append(index)

        print(f'错误的通道号为:{self.abnormal_signals}')

        # 显示错误信息
        self.erro_count = len(self.abnormal_signals)
        if self.erro_count > 0:
            # 显示错误信息
            self.erro_status_time.setText(str(self.erro_count))
            # 设置错误按钮的标志位
            self.erro_flag = True
            # 发送错误信息到错误信息定位槽函数
            self.project_erro_signal.emit(self.recv_erro_info_dict)

        # 显示错误信息到对应屏幕的通道上
        self.__set_channel_status(self.abnormal_signals,size=self.channel_length[int(self.Json_protocol.dataprotocol) - 1])

    def __on_project_timerout_dispaly(self):
        """
        接收超时显示函数：当在超时回调函数中，使用模态对话框显示期间，QMessageBox.exec_()方法会阻塞程序的主线程，直到对话框被关闭，
        期间所有的GUI事件处理都会暂停，包括窗口的绘制、键盘输入、鼠标移动等。
        当QMessageBox被展示时，用户的交互（如点击按钮关闭对话框）会被捕获并处理，但这同时也会触发GUI的事件循环去处理其他事件，
        比如Enter和Leave事件，这解释了为什么您的程序会“跳转”到eventFilter方法中
        解决方案：
            1.使用非模态对话框显示，QMessageBox.show()方法
            2.使用信号机制来触发信号槽
        :return:None
        """
        # 关闭进度条
        self.process_bar.close_progress_bar()
        # 弹出对话框
        MessageBox.msg_box("错误", "接收数据超时,请检查连接状态")
        self.__set_statuasbar_info('接收数据超时')

    """*************************** 超时检测机制的错误回调函数 ***********************************"""

    def timeout_callback(self):
        """
        接收超时回调函数
        :return:
        """
        if self.time_out.event.is_set():
            # 停止超时检测并关闭定时器
            self.time_out.stop()
            self.project_timerout_signal.emit()

    """*************************** 查看日志的槽函数 ***********************************"""

    @pyqtSlot()
    def on_log_clicked(self):
        """
        查看日志的槽函数
        :return:None
        """
        try:
            # 获取日志文件路径
            log_path = 'log.txt'
            # 打开日志文件
            # 根据操作系统决定使用哪种方式打开文件
            if platform.system() == "Windows":
                os.startfile(log_path)  # 适用于Windows
            elif platform.system() == "Darwin":  # macOS
                subprocess.call(["open", log_path])
            elif platform.system() == "Linux":
                subprocess.call(["xdg-open", log_path])  # Linux
            else:
                MessageBox.msg_box("错误", "不支持的操作系统")
                self.__log.logger.error("在不支持的操作系统上打开日志文件 ")

            self.__set_statuasbar_info('打开日志文件')

        except Exception as e:
            MessageBox.msg_box("错误", e)
            self.__log.logger.error(e)

    """*************************** Clear 按钮的槽函数 ***********************************"""

    @pyqtSlot()
    def on_Clear_clicked(self):
        """
        清空所有的LED的状态，恢复到默认状态
        :return:None
        """
        # 定义空的列表
        try:
            list = []
            # 清空状态
            self.__set_channel_status(list, 128 * 4)
            # 清空错误标志位，不可打开错误文件，需要重新测试之后才能打开
            self.erro_flag = False
            # 保存处理后的错误通道号的数据
            self.recv_erro_info_dict = {}
            # 创建接收消息的容器
            self.recv_list = []
            # 创建一个列表来存储异常的值
            self.abnormal_signals = []

            self.__set_statuasbar_info('所有状态已清空')

        except Exception as e:
            MessageBox.msg_box("错误", e)
            self.__log.logger.error(e)

    """*************************** UDP发送数据的槽函数 ***********************************"""

    @pyqtSlot()
    def on_Start_clicked(self):
        """
        发送按钮的槽函数
        :return:None
        """
        # 构造消息体的数据
        msg_data = bytes.fromhex('0' + self.Json_protocol.dataprotocol + self.start_test) + b'\x00\x00'
        msg_data = self.Json_protocol.json_pack(msg_data)

        # 判断网络是否连接
        if self.udp_logic.link_flag:
            # 发送数据
            self.udp_logic.udp_send(msg_data)

            # 更新发送器的次数
            self.send_count += 1
            self.__set_send_recv_info(1)

    """*************************** 打开文档的执行函数 ***********************************"""

    def __open_excel(self, file_path: str):
        """
        打开文档的执行函数
        :param file_path: 文件路径
        :return: None
        """
        # 根据操作系统决定使用哪种方式打开文件
        if platform.system() == "Windows":
            os.startfile(file_path)  # 适用于Windows
        elif platform.system() == "Darwin":  # macOS
            subprocess.call(["open", file_path])
        elif platform.system() == "Linux":
            subprocess.call(["xdg-open", file_path])  # Linux
        else:
            MessageBox.msg_box("提示", "无法识别的操作系统类型，无法执行打开文件操作。")
            self.__log.logger.error("无法识别的操作系统类型，无法执行打开文件操作。")

    """*************************** "参考表"按钮的槽函数 ***********************************"""
    @pyqtSlot()
    def on_View_clicked(self):
        """
        "参考表"按钮的槽函数
        :return:
        """
        try:
            # 定义路径
            file_path = None
            # 判断设备类型
            # 11B项目类型
            if self.Json_protocol.dataprotocol == '1':
                file_path = r'Doc\StandardForm\11B测试定义查询表格.xlsx'
            # 11bs项目类型
            elif self.Json_protocol.dataprotocol == '2':
                file_path = r'Doc\StandardForm\11BS测试定义查询表格.xlsx'
            # 15项目类型
            elif self.Json_protocol.dataprotocol == '3':
                file_path = r'Doc\StandardForm\15测试定义查询表格.xlsx'
            # 15s项目类型
            elif self.Json_protocol.dataprotocol == '4':
                file_path = r'Doc\StandardForm\15S测试定义查询表格.xlsx'
            else:
                self.__log.logger.error('打开错误表格时的项目类型参数出错，请检查Json配置文件')
                return False

            # 如果为有效路径
            if file_path:
                self.__open_excel(file_path)
            else:
                MessageBox.msg_box('提示', '打开参考误表格失败,请检查Json配置文件')
                self.__log.logger.error('由于Json配置项目类型出错导致获取文件路径失败，请检查Json配置文件')
                return False

        except Exception as e:
            self.__log.logger.error(f'打开参考表格失败，请检查文件是否存在，错误信息为{e}')
            MessageBox.msg_box('提示', '打开错误表格失败，请检查文件是否存在')
            return False
    """*************************** ERRO按钮的槽函数 ***********************************"""

    @pyqtSlot()
    def on_erro_clicked(self):
        """
        错误信息定位按钮的槽函数,用于打开错误信息的表格
        :return:None
        """
        if self.erro_flag:
            try:
                # 定义路径
                file_path = None
                # 判断设备类型
                # 11B项目类型
                if self.Json_protocol.dataprotocol == '1':
                    file_path = r'Doc\ErroForm\11B测试结果错误表格.xlsx'
                # 11bs项目类型
                elif self.Json_protocol.dataprotocol == '2':
                    file_path = r'Doc\ErroForm\11BS测试结果错误表格.xlsx'
                # 15项目类型
                elif self.Json_protocol.dataprotocol == '3':
                    file_path = r'Doc\ErroForm\15测试结果错误表格.xlsx'
                # 15s项目类型
                elif self.Json_protocol.dataprotocol == '4':
                    file_path = r'Doc\ErroForm\15S测试结果错误表格.xlsx'
                else:
                    self.__log.logger.error('打开错误表格时的项目类型参数出错，请检查Json配置文件')
                    return False

                # 如果为有效路径
                if file_path:
                    self.__open_excel(file_path)
                else:
                    MessageBox.msg_box('提示', '打开错误表格失败,请检查Json配置文件')
                    self.__log.logger.error('由于Json配置项目类型出错导致获取文件路径失败，请检查Json配置文件')
                    return False

            except Exception as e:
                self.__log.logger.error(f'打开错误表格失败，请检查文件是否存在，错误信息为{e}')
                MessageBox.msg_box('提示', '打开错误表格失败，请检查文件是否存在')
                return False
        elif self.send_count == 0:
            MessageBox.msg_box('提示', '请开始测试后再打开错误表格')
            self.__log.logger.error('请开始测试后再打开错误表格')
        else:
            MessageBox.msg_box('提示', '没有错误数据生成，无法打开错误表格')
            self.__log.logger.error('没有错误数据生成，无法打开错误表格')

    """*************************** 错误信息定位函数 ***********************************"""

    @pyqtSlot(dict)
    def __on_project_erro_signal(self, info: dict):
        """
        错误信息定位函数:用于将本次测试的错误数据生成在一个可快速定位的文档里面
        :return:None
        """

        status = None
        # 判断设备类型
        # 11B项目类型
        if self.Json_protocol.dataprotocol == '1':
            status = self.protocol_11b._11b_erro_info_save_excel(info)
        # 11bs项目类型
        elif self.Json_protocol.dataprotocol == '2':
            status = self.protocol_11bs._11bs_erro_info_save_excel(info)
        # 15项目类型
        elif self.Json_protocol.dataprotocol == '3':
            status = self.protocol_15._15_erro_info_save_excel(info)
        # 15s项目类型
        elif self.Json_protocol.dataprotocol == '4':
            status = self.protocol_15s._15s_erro_info_save_excel(info)
        else:
            self.__log.logger.error('错误信息定位时的项目类型参数出错，请检查Json配置文件')
            return False

        # 判断是否定位成功
        if status:
            MessageBox.msg_box('错误信息定位', '错误信息定位成功')
            self.__set_statuasbar_info('错误信息定位成功')
            self.__log.logger.info('错误信息定位成功')
        else:
            self.__log.logger.error('错误信息定位失败')
            MessageBox.msg_box('错误信息定位', '错误信息定位失败')
            return False

    """*************************** 获取Lable对象名称的函数 ***********************************"""

    def __get_lable_widget(self, i: int) -> QWidget or None:
        """
        根据通道索引获取对应的标签控件。
        :param i:通道索引
        :return: 对应的标签控件或None
        """
        index = min((i - 1) // 128 + 1, 3)  # i从1开始，因此减1再除以128，加1得到index，同时限制最大为3
        second_index = 128 if i in [128, 256] else i % 128
        label_name = f'led_{index}_{second_index}'
        return getattr(self, label_name, None)

    """*************************** 通道反馈显示函数 ***********************************"""

    def __set_channel_status(self, info: list, size: int):
        """
         设置通道的状态：如果没有错，就将状态设置为绿色，否则设置为红色。默认状态下颜色不变
        :param info:错误的数据列表
        :param size:数据长度
        :return:None
        """
        # 如果是操作所有的通道的话，就全部设置为默认样式
        if size == 128 * 4:
            # 设置通道为默认颜色
            for i in range(1, 513):
                lable_widget = self.__get_lable_widget(i)
                if lable_widget is not None:
                    lable_widget.setStyleSheet("background-color: rgb(124, 124, 124);border-radius:8px;")  # 默认色

        else:
            for i in range(1, size + 1):
                lable_widget = self.__get_lable_widget(i)
                if lable_widget is not None:
                    if i in info:
                        # 设置通道为红色
                        lable_widget.setStyleSheet("background-color: rgb(255, 0, 0);border-radius:8px;")
                        self.__log.logger.error(f'通道{i}错误')
                    else:
                        # 设置通道为绿色
                        lable_widget.setStyleSheet("background-color: rgb(0, 255, 0);border-radius:8px;")
                else:
                    self.__log.logger.error(f'设置指示灯状态时获取控件名称失败')

    """*************************** JSON协议类型槽函数 ***********************************"""

    @pyqtSlot(str)
    def __on_project_protocol(self, num: str):
        """
        Json协议类型的槽函数:用于解析JSON协议后，获取协议类型
        :param num:范围为1~4
        :return:None
        """
        if num == '1':
            self.protocol_11b._11b_initialize_hover_info()
        elif num == '2':
            self.protocol_11bs._11bs_initialize_hover_info()
        elif num == '3':
            self.protocol_15._15_initialize_hover_info()
        elif num == '4':
            self.protocol_15s._15s_initialize_hover_info()
        else:
            self.__log.logger.error('项目协议参数错误')

    """*************************** LOAD按钮的槽函数 ***********************************"""

    @pyqtSlot()
    def on_Load_clicked(self):
        """
        Load按钮的槽函数:用于加载JSON协议
        :return:成功 True, 失败 False
        """
        # 获取JSON文件路径
        path = self.Json_protocol.get_json_path()

        # 路径的有效性
        if path[0] and path[0] != '':
            self.__log.logger.info(f'正在导入JSON文件:{path}')

            # 判断是否加载成功
            if self.Json_protocol.json_load(path[0]):
                self.__log.logger.info('导入JSON文件成功')
                self.__set_statuasbar_info('导入JSON文件成功')

                # 使能全部控件
                self.__set_control_enable(2)
                # 发送项目协议信号
                self.project_protocol.emit(self.Json_protocol.dataprotocol)
                return True

            else:
                # 失能全部控件
                self.__set_control_enable(0)
                self.log.logger.info('导入JSON文件失败')
                MessageBox.msg_box('提示', '导入JSON文件失败，具体信息请查看日志文件')
                return False

        else:
            MessageBox.msg_box('提示', '未选择JSON文件')
            # 设置错误按钮的标志位
            self.erro_flag = False
            self.__log.logger.info('未选择JSON文件')
            return False

    """*************************** 接收数据解析槽函数 ***********************************"""

    def __on_project_recv_data_signal(self, info: bytes):
        """
        项目类型的协议解析槽函数：对已经经过JSON协议解析之后的消息体进行项目类型解析
        :param info:接收到的消息体数据
        :return:None
        """
        list_info = []

        # 调用公共解析函数
        list_info = self.public_data_process.public_data_process(info)

        # 如果列表为空，表明接收数据有问题
        if not list_info:
            return

        print(f'list_info:{list_info}')
        # 如果为起始帧
        if list_info[0] == int(self.start_test):
            # 获取通道长度
            self.lengh = list_info[1]
            # 清空接收计数器的长度
            self.rec_count = 0
            # 应答下位机
            self.udp_logic.udp_send(self.public_data_process.master_nck_slave())
            # 开启定时器
            self.time_out.start()
        # 判断是否为结束帧
        elif list_info[0] == int(self.trans_over):
            # 关闭定时器
            self.time_out.stop()
            # 清空接收计数器的长度
            self.rec_count = 0
            self.__log.logger.info('接收数据完成')
            # 释放开始解析数据的信号量
            self.project_data_process_signal.emit()

        # 判断是否为传输帧
        elif list_info[0] == int(self.trans_flag):
            # 获取数据
            self.recv_list.append(list_info[1:])
            # 应答下位机
            self.udp_logic.udp_send(self.public_data_process.master_nck_slave())
            # 判断通道号是否合法
            if list_info[3] <= self.lengh:
                # 判断当前通道编号是否和上一次的通道编号相等
                if self.channel_index != list_info[3]:
                    # 保存当前通道编号
                    self.channel_index = list_info[3]
                    # 计数器长度加一
                    self.rec_count += 1
            else:
                # 错误提醒
                MessageBox.msg_box('提示', '接收数据长度错误，请查看详细的日志')
                self.__log.logger.error('传输帧长度错误')
            # 重置定时器
            self.time_out.reset()

    """*************************** UDP接收信息的槽函数 ***********************************"""

    @pyqtSlot(bytes)
    def __on_udp_signal_write_info(self, info: bytes):
        """
        UDP接收数据的槽函数
        :param info:
        :return:
        """
        try:
            # 根据JSON协议来解析数据，返回解析后的消息体
            temp_data = self.Json_protocol.json_unpack(info, len(info))

            # 判断是否解析成功
            if temp_data is None:
                self.__log.logger.error('解析JSON协议数据失败')
                MessageBox.msg_box('提示', '解析JSON协议数据失败，具体信息请查看日志文件')
                return False

            print(f'status:{temp_data}')
            # 发送信号，再次根据具体的协议类型解析数据
            self.project_recv_data_signal.emit(temp_data)

            # 更新接收器的次数
            self.rec_count += 1
            self.__set_send_recv_info(2)
        except Exception as e:
            self.__log.logger.error(f'解析JSON协议数据失败:{e}')

    """*************************** UDP状态信息的槽函数 ***********************************"""

    @pyqtSlot(str)
    def __on_udp_signal_write_msg(self, msg: str):
        """
        UDP状态信息的槽函数
        :return:
        """
        print(f'udp_signal_send_msg:{msg}')
        self.__set_statuasbar_info(msg)

    """*************************** Connect按钮的槽函数 ***********************************"""

    @pyqtSlot()
    def on_Connect_clicked(self):
        """
        Connect按钮的槽函数,目的是连接网络
        :return:None
        """
        # 网络处于断开状态
        if not self.udp_logic.link_flag:
            # 判断IP和Port是否为空
            if self.IP_Edit.text() and self.Port_Edit.text():
                # 启动UDP客户端
                self.udp_logic.udp_client_start(self.IP_Edit.text(), int(self.Port_Edit.text()))

                # 改变Connect控件样式
                self.__change_connect_style()
                # 使能Load按钮
                self.__set_control_enable(1)
                # 设置状态栏信息
                self.__set_statuasbar_info("UDP客户端已启动")
            else:
                MessageBox.msg_box('提示', 'IP或Port为空，请重新输入')
                self.__log.logger.error('IP或Port为空')

        # 网络处于连接状态
        else:
            # 关闭UDP客户端
            self.udp_logic.udp_close()
            # 改变Connect控件样式
            self.__change_connect_style()
            # 失能所有按钮
            self.__set_control_enable(0)
            # 设置状态栏信息
            self.__set_statuasbar_info("UDP客户端已关闭")
            # 设置错误按钮的标志位
            self.erro_flag = False

    """*************************** 改变Connect控件样式 ***********************************"""

    def __change_connect_style(self):
        """
        改变Connect控件样式:当网络连接时改为Disconnect，否则改为Connect
        :return:
        """
        # 定义图标
        self.Connet_Icon = QIcon('UI/Qrc/Connect.png')
        self.Disconnect_Icon = QIcon('UI/Qrc/Disconnect.png')

        # 判断网络连接状态
        if self.udp_logic.link_flag:
            self.Connect.setText("Disconnect")
            self.Connect.setIcon(self.Connet_Icon)
        # 网络断开状态
        else:
            self.Connect.setText("Connect")
            self.Connect.setIcon(self.Disconnect_Icon)

    """*************************** 控件使能 ***********************************"""
    """控件使能的方法"""

    def __set_control_enable(self, num: int):
        """
        当网口连接之后需要将LOAD按钮施使能，当导入JSON协议成功之后，所有按钮控件使能。
        当网口断开连接之后，所有按钮控件失能
        :param num:0 表示网口断开连接，1表示网口连接，2表示导入JSON协议成功
        :return:
        """
        # 网口断开连接时，失能所有控件
        if num == 0:
            self.Start.setEnabled(False)
            self.Clear.setEnabled(False)
            self.Load.setEnabled(False)
            self.Stop.setEnabled(False)
            self.View.setEnabled(False)
            self.log.setEnabled(False)
            self.erro.setEnabled(False)
        # 网口连接时，先使能LOAD按钮
        elif num == 1:
            self.Load.setEnabled(True)
        # 导入JSON协议成功时，使能所有控件
        elif num == 2:
            self.Start.setEnabled(True)
            self.Clear.setEnabled(True)
            self.Load.setEnabled(True)
            self.Stop.setEnabled(True)
            self.View.setEnabled(True)
            self.log.setEnabled(True)
            self.erro.setEnabled(True)
        else:
            self.__log.log.error("__set_control_enable函数传入参数错误")
            return -1

    """*************************** 状态栏信息 ***********************************"""

    def __set_send_recv_info(self, num: int):
        """
        设置发送和接收信息的次数信息
        :param num:1 表示更新发送信息的次数  2 表示更新接收信息的次数     3 表示复位信息
        :return:None
        """
        if num == 1:
            self.send_status_time.setText(str(self.send_count))
        elif num == 2:
            self.recv_status_time.setText(str(self.rec_count))
        elif num == 3:
            self.send_count = 0
            self.rec_count = 0
            self.erro_count = 0
            self.erro_status_time.setText(str(self.erro_count))
            self.send_status_time.setText(str(self.send_count))
            self.recv_status_time.setText(str(self.rec_count))
        else:
            self.__log.log.error("设置发送和接收次数传入参数错误")

    def __set_statuasbar_info(self, msg: str):
        """
        设置状态栏信息
        :param msg:更改"连接状态"信息
        :return:None
        """
        self.connect_status.setText(msg)

    def __ResetLable_Init(self):
        """
        初始化设置"复位"标签的事件捕获功能
        :return:None
        """
        self.label_clickable = self.findChild(QLabel, "status_reset")  # 找到复位标签
        self.label_clickable.mousePressEvent = self.labelClicked  # 重写鼠标点击事件处理

    @pyqtSlot()
    def labelClicked(self, event):
        """
        复位标签的点击事件处理
        :param event:鼠标的点击事件
        :return:None
        """
        if event.button() == Qt.LeftButton:
            self.__set_send_recv_info(3)


"""主函数入口"""
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()
